//
// $Id: ChessTheme.java 8 2007-04-18 13:47:40Z z_hossain $
//
// xChess is a multiplatform graphical chess user interface
// Copyright (C) 2007  MD. Z. Hossain <z_hossain@users.sf.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
// 02110-1301, USA.
//
// For more information visit http://xchess.sourceforge.net
//

package gui;


import java.awt.Dimension;
import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ChessTheme {
	
	private String themePath;
		
	private static ChessTheme chessTheme = new ChessTheme();
	private HashMap<String, String> themeMap = new HashMap<String, String>();
	
	private Image[] squareImages = new Image[2];
	private Image[] pieceImages = new Image[PiecesUI.PIECE_TOTAL];
	private Image[] highlightImages = new Image[2];
	
	private ChessTheme() {
		themePath = "xchess://net/sourceforge/xchess/images/theme.xml";
		loadTheme();
	}
		
	class ThemeHandler extends DefaultHandler {
		
		String themeKey = new String();
		
		@Override
		public void characters(char[] ch, int start, int length) throws SAXException {
			String themeValue = new String(ch, start, length).trim();
			if(themeKey.length() > 1 && themeValue.length() > 0) {
				themeMap.put(themeKey.substring(1), themeValue);
			}
		}

		@Override
		public void endElement(String uri, String localName, String qName) throws SAXException {
			if(!qName.equals("theme")) 
				themeKey = themeKey.substring(0, themeKey.lastIndexOf(':'));
		}

		@Override
		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
			if(qName.equals("theme")) {
				if(!attributes.getValue("specification").equals("1.0"))
					throw new UnsupportedOperationException("Unsupported Specification Version");
			} 
			else themeKey = themeKey + ":" + qName;
		}
	}
	
	private void loadTheme() {
		try {
			ThemeHandler themeHandler = new ThemeHandler();
			SAXParserFactory factory = SAXParserFactory.newInstance();
			 SAXParser saxParser = factory.newSAXParser();
			saxParser.parse(getStream(themePath), themeHandler);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		squareImages[BoardUI.SQUARE_WHITE] = getImage(themeMap.get("board:square:light"));
		squareImages[BoardUI.SQUARE_BLACK] = getImage(themeMap.get("board:square:dark"));
						
		pieceImages[PiecesUI.WHITE_PAWN] = getImage(themeMap.get("pieces:white:pawn"));
		pieceImages[PiecesUI.WHITE_KNIGHT] = getImage(themeMap.get("pieces:white:knight"));
		pieceImages[PiecesUI.WHITE_BISHOP] = getImage(themeMap.get("pieces:white:bishop"));
		pieceImages[PiecesUI.WHITE_ROOK] = getImage(themeMap.get("pieces:white:rook"));
		pieceImages[PiecesUI.WHITE_QUEEN] = getImage(themeMap.get("pieces:white:queen"));
		pieceImages[PiecesUI.WHITE_KING] = getImage(themeMap.get("pieces:white:king"));
		
		pieceImages[PiecesUI.BLACK_PAWN] = getImage(themeMap.get("pieces:black:pawn"));
		pieceImages[PiecesUI.BLACK_KNIGHT] = getImage(themeMap.get("pieces:black:knight"));
		pieceImages[PiecesUI.BLACK_BISHOP] = getImage(themeMap.get("pieces:black:bishop"));
		pieceImages[PiecesUI.BLACK_ROOK] = getImage(themeMap.get("pieces:black:rook"));
		pieceImages[PiecesUI.BLACK_QUEEN] = getImage(themeMap.get("pieces:black:queen"));
		pieceImages[PiecesUI.BLACK_KING] = getImage(themeMap.get("pieces:black:king"));
		
		highlightImages[BoardUI.HIGHLIGHT_SELECT] = getImage(themeMap.get("board:highlight:select"));
		highlightImages[BoardUI.HIGHLIGHT_MOVE] = getImage(themeMap.get("board:highlight:move"));
		
		themeMap.clear();
	}
	
	private Image getImage(String path) {
		try {
			if(path.startsWith("xchess://"))
				return new ImageIcon(ImageIO.read(getClass().getClassLoader()
						.getResource(path.substring(9)))).getImage();
			else return new ImageIcon(ImageIO.read(new File(new File(themePath)
				.getParentFile(), path))).getImage();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static ChessTheme getChessTheme() {
		return chessTheme;
	}
	
	public Image getSquareImage(int id) {
		return squareImages[id];
	}
	
	public Image getPieceImage(int id) {
		return pieceImages[id];
	}
	
	public Image getHighlight(int id) {
		return highlightImages[id];
	}
	
	public void adjustTheme(Dimension dimension) {
		loadTheme();
		
		int swidth = (int) (dimension.width / (double) BoardUI.FILE_RANK);
		int sheight = (int) (dimension.height / (double) BoardUI.FILE_RANK);
		
		squareImages[BoardUI.SQUARE_WHITE] 
		             = scaleImage(squareImages[BoardUI.SQUARE_WHITE], swidth, sheight);
		squareImages[BoardUI.SQUARE_BLACK] 
		             = scaleImage(squareImages[BoardUI.SQUARE_BLACK], swidth, sheight);
		
		for(int i = 0; i < PiecesUI.PIECE_TOTAL; i++) {
			pieceImages[i] = scaleImage(pieceImages[i], swidth, sheight);
		}
		
		highlightImages[BoardUI.HIGHLIGHT_SELECT] 
		        = scaleImage(highlightImages[BoardUI.HIGHLIGHT_SELECT], swidth, sheight);
		highlightImages[BoardUI.HIGHLIGHT_MOVE] 
		        = scaleImage(highlightImages[BoardUI.HIGHLIGHT_MOVE], swidth, sheight);
	}
	
	private Image scaleImage(Image image, int swidth, int sheight) {
		return image.getScaledInstance(swidth, sheight, Image.SCALE_SMOOTH);
	}
	
	private InputStream getStream(String path) {
		try {
			if(path.startsWith("xchess://"))
				return new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(path.substring(9)));
			else
				return new BufferedInputStream(new FileInputStream(new File(path)));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}
